/*
 * XQServiceFactory.java
 */

package xq.api;

import java.net.URI;
import java.util.Map;
import java.util.ServiceLoader;

/**
 *
 * @author ThorntonRP
 */
public abstract class XQServiceFactory {

	public static XQService getService(URI connectionURI) throws XQConfigException {
		ServiceLoader<XQServiceFactory> factories = ServiceLoader.load(XQServiceFactory.class);
		return findService(connectionURI, null, factories);
	}
	
	public static XQService getService(URI connectionURI, Map<String, ? extends Object> properties) throws XQConfigException {
		ServiceLoader<XQServiceFactory> factories = ServiceLoader.load(XQServiceFactory.class);
		return findService(connectionURI, properties, factories);
	}
	
	public static XQService getService(URI connectionURI, ClassLoader loader) throws XQConfigException {
		ServiceLoader<XQServiceFactory> factories = ServiceLoader.load(XQServiceFactory.class, loader);
		return findService(connectionURI, null, factories);
	}
	
	public static XQService getService(URI connectionURI, Map<String, ? extends Object> properties, ClassLoader loader) throws XQConfigException {
		ServiceLoader<XQServiceFactory> factories = ServiceLoader.load(XQServiceFactory.class, loader);
		return findService(connectionURI, properties, factories);
	}
	
	public abstract boolean acceptsURI(URI connectionURI);
	
	public abstract XQService create(URI connectionURI) throws XQConfigException;

	public abstract XQService create(URI connectionURI, Map<String, ? extends Object> properties) throws XQConfigException;

	/*--------------------------------------------------------------------
	 * Private Implementation
	 *--------------------------------------------------------------------*/
	
	private static XQService findService(URI connectionURI, Map<String, ? extends Object> properties, Iterable<XQServiceFactory> factories) throws XQConfigException {
		for (XQServiceFactory factory : factories) {
			if (factory.acceptsURI(connectionURI)) {
				return factory.create(connectionURI, properties);
			}
		}
		throw new XQConfigException("No XQServiceFactory implementation found that handles URI.");
	}
}
